package top.v5it.japi.plus.common.func;

import java.util.Objects;
import java.util.function.Function;

/**
 * 自定义函数接口
 *
 * @author zhanpu
 * @date 2018/12/18
 */
@FunctionalInterface
public interface Func1<T, R, E extends Throwable> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     * @throws E
     */
    R apply(T t) throws E;

    /**
     * 处理往外抛异常
     *
     * @param before
     * @param <V>
     * @return
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);

        return (V v) -> {
            try {
                return apply(before.apply(v));
            } catch (Throwable e) {
                throw new FuncException(e);
            }
        };

    }

    /**
     * 处理往外抛异常
     *
     * @param after
     * @param <V>
     * @return
     */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);

        return (T t) -> {
            try {
                return after.apply(apply(t));
            } catch (Throwable e) {
                throw new FuncException(e);
            }
        };
    }

    /**
     * 基于本函数返回{@link FuncException}
     *
     * @param t 参数
     * @return R 返回值
     */
    default R applyWithFuncException(T t) {
        try {
            return apply(t);
        } catch (Throwable e) {
            throw new FuncException(e);
        }
    }

}
